#pragma once

#include <string>
#include <sstream>

namespace format {

    class Format {

    public:

        /**
          * @brief  构造Format对象
          * @note   {0}表示第一个参数,{1}表示第二个参数...
          * @param  要进行格式化的字符串、填充参数...
          */
        template<class ...Args>
        explicit Format(std::string str, Args &&...args) {
            int n = sizeof...(Args);
            string_n_format(str, n, std::forward<Args>(args)...);
            string_format = str;
        }

        template<class ...Args>
        explicit Format(const char *str, Args &&...args) : Format(std::string(str), std::forward<Args>(args)...) {}

        /**
          * @brief  重载<<运算符
          */
        friend std::ostream &operator<<(std::ostream &out, const Format &format) {
            out << format.string_format;
            return out;
        }

        /**
          * @brief  允许与std::string进行类型转换
          */
        operator std::string() const { return string_format; }

        ~Format() = default;

        Format(Format &) = delete;

        Format(Format &&) = delete;

        Format &operator=(Format &) = delete;

    private:

        Format() = default;

        template<class T>
        void string_n_format(std::string &str, const int &n, T &&t) {
            std::string sub = '{' + std::to_string(n - 1) + '}';
            std::stringstream dest;
            dest << t;
            str.replace(str.find(sub), 3, dest.str());
        }

        template<class T, class ...Args>
        void string_n_format(std::string &str, const int &n, T &&t, Args &&...args) {
            std::string sub = '{' + std::to_string(n - sizeof...(Args) - 1) + '}';
            std::stringstream dest;
            dest << t;
            str.replace(str.find(sub), 3, dest.str());
            string_n_format(str, n, std::forward<Args>(args)...);
        }

        std::string string_format;

    };

}
